﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Media;
using BTM_Client_Application.RealTimeFilter;

namespace BTM_Client_Application.SupportClasses
{
    internal class LogRecord : IRealTimeFilterObject
    {
        public delegate LogRecord LogRecordWorkDelegate(LogRecord record, Dictionary<string, List<object>> req);

        #region props

        private static readonly string _regionTitle = Res.Rm.GetString("Region", AliveInfo.CurrentCulture);
        private static readonly string _blrTitle = Res.Rm.GetString("FrequencyZone", AliveInfo.CurrentCulture);
        private static readonly string _stationTitle = Res.Rm.GetString("Station", AliveInfo.CurrentCulture);
        private static readonly string _deviceTitle = Res.Rm.GetString("Device", AliveInfo.CurrentCulture);

        private static readonly string _severityTitle = Res.Rm.GetString("Severity", AliveInfo.CurrentCulture);
        private static readonly string _eventTitle = Res.Rm.GetString("Event", AliveInfo.CurrentCulture);
        private static readonly string _sourceTitle = Res.Rm.GetString("Source", AliveInfo.CurrentCulture);
        private static readonly string _infoTitle = Res.Rm.GetString("Info", AliveInfo.CurrentCulture);

        private static readonly string _startTimeTitle = Res.Rm.GetString("StartTime", AliveInfo.CurrentCulture);
        private static readonly string _endTimeTitle = Res.Rm.GetString("EndTime", AliveInfo.CurrentCulture);

        private static readonly string _timeTitle = Res.Rm.GetString("Time", AliveInfo.CurrentCulture);
        private static readonly string _infoGridColumnTitle = Res.Rm.GetString("AdditionalInfo", AliveInfo.CurrentCulture);

        public static string RegionTitle
        {
            get { return _regionTitle; }
        }

        public static string BlrTitle
        {
            get { return _blrTitle; }
        }

        public static string StationTitle
        {
            get { return _stationTitle; }
        }

        public static string DeviceTitle
        {
            get { return _deviceTitle; }
        }

        public static string SeverityTitle
        {
            get { return _severityTitle; }
        }

        public static string EventTitle
        {
            get { return _eventTitle; }
        }

        public static string SourceTitle
        {
            get { return _sourceTitle; }
        }

        public static string InfoTitle
        {
            get { return _infoTitle; }
        }

        public static string StartTimeTitle
        {
            get { return _startTimeTitle; }
        }

        public static string EndTimeTitle
        {
            get { return _endTimeTitle; }
        }

        public static List<string> GetLogData(Dictionary<string, List<object>> req)
        {
            var regions = new StringBuilder("");
            if (req.ContainsKey(RegionTitle))
                regions = ParameterslistToString(req[RegionTitle]);

            var blrs = new StringBuilder("");
            if (req.ContainsKey(BlrTitle))
                blrs = ParameterslistToString(req[BlrTitle]);

            var stations = new StringBuilder("");
            if (req.ContainsKey(StationTitle))
                stations = ParameterslistToString(req[StationTitle]);

            var devices = new StringBuilder("");
            if (req.ContainsKey(DeviceTitle))
                devices = ParameterslistToString(req[DeviceTitle]);

            var logData = AliveInfo.ClientHelper.GetLogFromServer(regions.ToString(), blrs.ToString(),
                                                                  stations.ToString(),
                                                                  devices.ToString(),
                                                                  (DateTime)req[StartTimeTitle][0],
                                                                  (DateTime)req[EndTimeTitle][0]);

            var st = logData.ToString();
            return st.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries).ToList();
        }

        public static List<LogRecord> WorkLogData(Dictionary<string, List<object>> req, LogRecordWorkDelegate del = null)
        {
            var list = GetLogData(req);

            var toRet = new List<LogRecord>();

            var events = new List<object>();
            try
            {
                events = req[LogRecord.EventTitle];
            }
            catch (Exception)
            {

            }

            foreach (var record in list)
            {
                const int regionPos = 0;
                const int blrPos = 1;
                const int devicePos = 2;
                const int stationPos = 3;
                const int severityPos = 4;
                const int eventPos = 5;
                const int sourcePos = 6;
                const int infoPos = 7;
                const int timePos = 8;

                var props = record.Split(new[] {';'}, StringSplitOptions.None);
                DateTime date;
                try
                {
                    date = DateTime.Parse(props[timePos]);
                }
                catch (Exception)
                {
                    continue;
                }

                var lRecord = new LogRecord(props[regionPos], props[blrPos], props[devicePos], props[stationPos],
                                            props[severityPos], props[eventPos], props[sourcePos], props[infoPos],
                                            date);
                //Filter events
                bool contains = true;
                if (events.Count > 0)
                {
                    contains = false;
                    if (!events.Contains(lRecord.Event))
                    {
                        if (events.Cast<string>().Any(ev => lRecord.Event.Contains(ev)))
                        {
                            contains = true;
                        }
                    }
                    else
                    {
                        contains = true;
                    }
                }
                if(!contains)
                    continue;
                if(del == null)
                    toRet.Add(lRecord);
                else
                {
                    var r = del(lRecord, req);
                    if (r != null)
                        toRet.Add(r);
                }
                
            }
            return toRet;
        }

        #endregion

        static LogRecord()
        {

            var availableDevices = new List<object>(AliveInfo.MegaDeviceTree.Devices.Count);

            foreach (var device in AliveInfo.MegaDeviceTree.Devices.OrderBy(x => x.DevInfo.Title))
            {
                availableDevices.Add(device.DevInfo.Title);
            }

            var availableStations = new List<object>(AliveInfo.MegaDeviceTree.Stations.Count);

            foreach (var station in AliveInfo.MegaDeviceTree.Stations.OrderBy(x => x.Info.Station))
            {
                availableStations.Add(station.Info.Station);
            }

            var availableRegions = new List<object>(AliveInfo.MegaDeviceTree.Regions.Count);

            foreach (
                var region in AliveInfo.MegaDeviceTree.Regions.OrderBy(x => x.ToString(CultureInfo.InvariantCulture)))
            {
                availableRegions.Add(region);
            }

            var availableBlrs = new List<object>(AliveInfo.MegaDeviceTree.Blrs.Count);

            foreach (var blr in AliveInfo.MegaDeviceTree.Blrs.OrderBy(x => x.ToString(CultureInfo.InvariantCulture)))
            {
                availableBlrs.Add(blr);
            }

            _filterInterface = new Dictionary<string, FilterElementInitializer>();
            _filterInterface.Add(_regionTitle,
                                 new FilterElementInitializer(FilterElementType.StringList, availableRegions,
                                                              new DataGridColumnInitializer(_regionTitle, "Region")));
            _filterInterface.Add(_blrTitle,
                                 new FilterElementInitializer(FilterElementType.StringList, availableBlrs,
                                                              new DataGridColumnInitializer(_blrTitle, "Blr")));
            _filterInterface.Add(_stationTitle,
                                 new FilterElementInitializer(FilterElementType.StringList, availableStations,
                                                              new DataGridColumnInitializer(_stationTitle, "Station")));
            _filterInterface.Add(_deviceTitle,
                                 new FilterElementInitializer(FilterElementType.StringList, availableDevices,
                                                              new DataGridColumnInitializer(_deviceTitle, "Device")));
            _filterInterface.Add(_severityTitle,
                                 new FilterElementInitializer(FilterElementType.NoControl, null,
                                                              new DataGridColumnInitializer(_severityTitle, "Severity")));
            _filterInterface.Add(_eventTitle,
                                 new FilterElementInitializer(FilterElementType.StringListContains, null,
                                                              new DataGridColumnInitializer(_eventTitle, "Event")));
            _filterInterface.Add(_sourceTitle,
                                 new FilterElementInitializer(FilterElementType.NoControl, null,
                                                              new DataGridColumnInitializer(_sourceTitle, "Source")));
            _filterInterface.Add(_infoTitle,
                                 new FilterElementInitializer(FilterElementType.NoControl, null,
                                                              new DataGridColumnInitializer(_infoGridColumnTitle, "Info")));
            _filterInterface.Add(_startTimeTitle,
                                 new FilterElementInitializer(FilterElementType.StartTime, null,
                                                              new DataGridColumnInitializer(_timeTitle, "StartTime")));
            _filterInterface.Add(_endTimeTitle,
                                 new FilterElementInitializer(FilterElementType.EndTime, null, null));

            _filterElements = new Dictionary<string, object>();
        }

        public LogRecord()
        {

        }

        public LogRecord(string region, string blr, string device, string station, string severity, string eventData,
                         string source, string info, DateTime startTime)
        {
            Region = region;
            Blr = blr;
            Station = station;
            Device = device;
            Severity = severity;
            StartTime = startTime;
            Event = eventData;
            Source = source;
            Info = info;
        }

        public Brush ItemBackground { get; set; }

        public string Region { get; private set; }
        public string Blr { get; private set; }
        public string Device { get; private set; }
        public string Station { get; private set; }
        public string Severity { get; private set; }
        public string Event { get; private set; }
        public string Source { get; private set; }
        public string Info { get; private set; }
        public DateTime StartTime { get; private set; }
        public string EndTime { get; private set; }

        public override int GetHashCode()
        {
            return Region.GetHashCode() ^ Blr.GetHashCode() ^ Device.GetHashCode() ^ Station.GetHashCode() ^
                   Severity.GetHashCode() ^ Event.GetHashCode() ^ Source.GetHashCode() ^ Info.GetHashCode() ^
                   StartTime.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            var another = obj as LogRecord;
            if (another == null)
                return false;
            return another.GetHashCode() == GetHashCode();
        }

        // ReSharper disable InconsistentNaming
        private static readonly Dictionary<string, FilterElementInitializer> _filterInterface;
        private static readonly Dictionary<string, object> _filterElements;
        // ReSharper restore InconsistentNaming

        public Dictionary<string, FilterElementInitializer> FilterInterface
        {
            get { return _filterInterface; }
        }

        public Dictionary<string, object> FilterElements
        {
            get { return _filterElements; }
        }
        
        private static StringBuilder ParameterslistToString(IEnumerable<object> list)
        {
            var sb = new StringBuilder();
            foreach (var o in list)
            {
                sb.Append(o + ",");
            }
            if (sb.Length > 0)
                sb.Remove(sb.Length - 1, 1);
            return sb;
        }
    }
}
